﻿#include "TesMatrix2x2.h"
#include "TesVector2.h"
#include <assert.h>
#include "TesMatrix3x3.h"
#include "TesMatrix4x4.h"

void TesMatrix2x2::Zero()
{
	M11_2 = M12_2 = M21_2 = M22_2 = 0.0f;
}

TesMatrix2x2::TesMatrix2x2()
{
	Zero();
}

void TesMatrix2x2::SetMatrix(float ma[4])
{
	M11_2 = ma[0];
	M12_2 = ma[1];
	M21_2 = ma[2];
	M22_2 = ma[3];
}

TesMatrix2x2::TesMatrix2x2(float ma[4])
{
	SetMatrix(ma);
}

void TesMatrix2x2::SetMatrix(float m11, float m12, float m21, float m22)
{
	this->M11_2 = m11;
	this->M12_2 = m12;
	this->M21_2 = m21;
	this->M22_2 = m22;
}

TesMatrix2x2& TesMatrix2x2::operator = (const TesMatrix2x2& that)
{
	M11_2 = that.M11_2;
	M12_2 = that.M12_2;
	M21_2 = that.M21_2;
	M22_2 = that.M22_2;
	return *this;
}

void TesMatrix2x2::Identity()
{
	M11_2 = M22_2 = 1.0f;
	M12_2 = M21_2 = 0.0f;
}

TesMatrix2x2 TesMatrix2x2::operator + (const TesMatrix2x2& that)
{
	TesMatrix2x2 Mat;
  Mat.M11_2 = M11_2 + that.M11_2;
  Mat.M12_2 = M12_2 + that.M12_2;
  Mat.M21_2 = M21_2 + that.M21_2;
  Mat.M22_2 = M22_2 + that.M22_2;
	return Mat;
}

TesMatrix2x2 TesMatrix2x2::operator - (const TesMatrix2x2& that)
{
	TesMatrix2x2 Mat;
  Mat.M11_2 = M11_2 - that.M11_2;
  Mat.M12_2 = M12_2 - that.M12_2;
  Mat.M21_2 = M21_2 - that.M21_2;
  Mat.M22_2 = M22_2 - that.M22_2;
	return Mat;
}

TesMatrix2x2 TesMatrix2x2::operator * (const TesMatrix2x2& that)
{
	TesMatrix2x2 Mat;
  Mat.M11_2 = M11_2 * that.M11_2 + M12_2 * that.M21_2;
  Mat.M11_2 = M11_2 * that.M12_2 + M12_2 * that.M22_2;
  Mat.M21_2 = M21_2 * that.M11_2 + M22_2 * that.M21_2;
  Mat.M21_2 = M21_2 * that.M12_2 + M22_2 * that.M22_2;
	return Mat;
}

float TesMatrix2x2::Determinant()
{
	return (M11_2 * M22_2 - M12_2 * M21_2);
}

TesMatrix2x2 TesMatrix2x2::Transpose()
{
	TesMatrix2x2 Mat;
	Mat.m2x2[0] = M11_2;
	Mat.m2x2[1] = M21_2;
	Mat.m2x2[2] = M12_2;
	Mat.m2x2[3] = M22_2;
	return Mat;
}

TesMatrix2x2 TesMatrix2x2::SetScale(float x, float y)
{
	Identity();
	M11_2 = x;
	M22_2 = y;
	return *this;
}

TesMatrix2x2 TesMatrix2x2::SetRotation(float Redus)
{
	M11_2 = cosf(Redus);
	M12_2 = -sinf(Redus);
	M21_2 = sinf(Redus);
	M22_2 = cosf(Redus);
	return *this;
}

float TesMatrix2x2::_Cofactor(int r, int c)
{
	float Factor = powf(-1.0f, float(r + c));
	assert(r == 1 || r == 2 || c == 1 || c == 2);//二维矩阵取行列不合法
	float Result = 0.0f;
	if (c == 1)
	{
		if (r == 1)
		{
			Result = Factor * M22_2;
		}
		else
		{
			Result = Factor * M21_2;
		}
	}
	else
	{
		if (r == 1)
		{
			Result = Factor * M12_2;
		}
		else
		{
			Result = Factor * M11_2;
		}
	}
	return Result;
}

TesMatrix2x2 TesMatrix2x2::_AdjoinMatrix()
{
	TesMatrix2x2 Result;
	Result.Zero();
	Result.M11_2 = _Cofactor(1, 1);
	Result.M12_2 = _Cofactor(2, 1);
	Result.M21_2 = _Cofactor(1, 2);
	Result.M22_2 = _Cofactor(2, 2);
	Result.Transpose();
	return Result;
}

TesMatrix2x2 TesMatrix2x2::operator * (const float& K) const
{
	TesMatrix2x2 R;
	R.M11_2 = M11_2 * K;
	R.M12_2 = M12_2 * K;
	R.M21_2 = M21_2 * K;
	R.M22_2 = M22_2 * K;
	return R;
}

TesMatrix2x2 TesMatrix2x2::operator / (const float& K)
{
	assert(K != 0.0f);
	TesMatrix2x2 R;
	R.M11_2 = M11_2 / K;
	R.M12_2 = M12_2 / K;
	R.M21_2 = M21_2 / K;
	R.M22_2 = M22_2 / K;
	return R;
}

TesMatrix2x2 TesMatrix2x2::Inverse()
{
	TesMatrix2x2 ad = _AdjoinMatrix();
	float Det = Determinant();
	//如果矩阵的行列式为0，这种方法无法求出逆。但是可以通增广矩阵法手动演算
	assert(Det != 0.0f); 
	ad = ad / Det;
	return ad;
}

void TesMatrix2x2::_GetToArray(float matrix[4])
{
	matrix[0] = M11_2;
	matrix[1] = M12_2;
	matrix[2] = M21_2;
	matrix[3] = M22_2;
}
TesMatrix3x3 TesMatrix2x2::ExtendToMatrix3x3()
{
	TesMatrix3x3 Res;
	Res.SetMatrix(*this);
	return Res;
}

TesMatrix4x4 TesMatrix2x2::ExtendToMatrix4x4()
{
	TesMatrix4x4 Res;
	Res.Zero();
	Res.M44_4 = 1.0f;
	Res.M11_4 = M11_2;
	Res.M12_4 = M12_2;
	Res.M21_4 = M21_2;
	Res.M22_4 = M22_2;
	return Res;
}

TesVector2 operator * (const TesVector2& v, const TesMatrix2x2& matrix)
{
	TesVector2 Result;
	Result.x = v.x * matrix.M11_2 + v.y * matrix.M21_2;
	Result.y = v.x * matrix.M12_2 + v.y * matrix.M22_2;
	return Result;
}

TesMatrix2x2 operator * (const float& K, const TesMatrix2x2& matrix)
{
	return matrix * K;
}